//
// Created by QU on 24-6-21.
//

// c++仿函数(Functor).
/**
 * 在C++中，仿函数（Functor）是一种可以像函数一样调用的*对象*。具体来说，仿函数是重载了operator()操作符的类的实例。
 * 仿函数可以持有状态和参数，与普通函数相比，具有更大的灵活性和功能。它们广泛用于标准模板库（STL）中的算法和容器操作。
 */

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

// 定义一个仿函数类
class MultiplyBy {
public:
    MultiplyBy(int factor) : factor(factor) {}

    // 重载()操作符
    int operator()(int x) const {
        return x * factor;
    }

private:
    int factor;
};


// 定义一个仿函数类
class Closure {
public:
    Closure(int factor) : factor(factor) {}

    // 重载()操作符
    int operator()(int x) const {
        return x * factor;
    }

private:
    int factor;
};


int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    std::vector<int> results(numbers.size());

    // 使用std::transform和仿函数
    std::transform(numbers.begin(), numbers.end(), results.begin(), MultiplyBy(2));

    for (int result : results) {
        std::cout << result << " "; // 输出2 4 6 8 10
    }

    ///////////////////////////////////////////////////////////

    // 创建一个Closure对象，初始值为10
    Closure multiplyBy10(10);
    /** 类保存了一个状态变量factor，并在调用operator()时使用该状态变量。这样，multiplyBy对象就类似于一个捕获了factor变量的闭包。 */
    std::cout << multiplyBy10(5) << std::endl; // 输出50

    // 此外，从C++11开始，C++引入了std::function和lambda表达式，使得实现闭包变得更加直接和简洁。使用lambda表达式可以更方便地创建闭包：
    int factor = 10;

    // 使用lambda表达式创建闭包
    std::function<int(int)> multi = [factor](int x) {
        return x * factor;
    };
    // 使用闭包
    std::cout << multi(5) << std::endl; // 输出50

    return 0;
}
